
--[[
    红点处理 红点树
    node
        parent -- 父节点
        children --子节点
        checkFunc(node, isNewChange) --检查函数 参数 isNewChange 标识有新的数据变化导致 从新检测红点（主要用于是否可以清除点击过的状态）
        state -- 当前状态
        key --
        isManual -- 操作到不满足逻辑才会消失的红点
]]

local DataModel = import(".DataModel")
local RedPonit = class("RedPonit", DataModel)
require("app.ui.RedPointHandler")

function RedPonit:ctor(  )
	-- body
	RedPonit.super.ctor(self)
    self:clear()
end

function RedPonit:clear()
    self._redPointRoot = {}
    self._changeKeys = {}
    self._cronsIdx = nil
end

function RedPonit:init()
    self:clear()
    RedPointHandler.init()
end


function RedPonit:hasKey(key)
    local node = self._redPointRoot[key]
    if not node then
        return false
    end
    return true
end

function RedPonit:initByKey(key, isNeedDisPatch)
    local node = self._redPointRoot[key]
    if not node then
        return
    end
    if isNeedDisPatch == nil then
        isNeedDisPatch = true
    end
    self:_initNode(node, isNeedDisPatch)
end

function RedPonit:_initNode(node, isNeedDisPatch)
    local state = false
    if node.children then
        for k, v in pairs(node.children) do
            self:_initNode(v, isNeedDisPatch)
            if v.state then
                state = true
            end
        end
    end

    if state == false and node.checkFunc then
        state = node.checkFunc(node)
    end

    node.state = state
    if isNeedDisPatch then
        self:_dispatchRedPonitChange(node)
    end
end

-- 当 checkFunc 为 nil 节点为临时红点（既 点击过后就关闭）
-- isManual 操作到不满足逻辑才会消失的红点
function RedPonit:newRedPointCheckNode(key, parentKey, checkFunc, defaultState, isManual)
    local node =  {
        state = defaultState ~= nil and defaultState or false,
        children = nil,
        parent = nil,
        key = key,
        checkFunc = checkFunc,
        isManual = isManual or false
    }
    if parentKey then
        local parentNode = self._redPointRoot[parentKey]
        if parentNode then
            if not parentNode.children then
                parentNode.children = {}
            end
            parentNode.children[key] = node
            node.parent = parentNode
        end
    end
    self._redPointRoot[key] = node
end

-- 直接设置 当前node 的红点状态
function RedPonit:setStateByKey(key, state)
    -- print("====> RedPoint setStateByKey", key, state)
    assert(state ~= nil, "please set state true or false \n"..debug.traceback()) 
    local node = self._redPointRoot[key]
    if not node then
        return
    end
    
    if node.state == state then
        return
    end
    -- print("====> RedPoint setStateByKey succ", key, state)
    node.state = state
    self:_dispatchRedPonitChange(node)
    self:_checkParentState(node)

    -- self:_debug()
end

function RedPonit:getStateByKey(key)
    local node = self._redPointRoot[key]
    if not node then
        return false
    end
    return node.state
end

-- 清理state
-- isRecursive 是递归
function RedPonit:clearStateByKey(key, isRecursive)
    local node = self._redPointRoot[key]
    if not node then return end

    -- print("====> RedPoint clearStateByKey", key)

    local oldState = node.state
    local newState = oldState
    if not node.isManual then
        newState = false
    end

    if oldState == newState then return end

    -- print("====> RedPoint clearStateByKey succ", key, newState, node.isManual)

    if not isRecursive then
        -- 非递归清理更新父节点的state：清理state时，对父节点而言，自己必定是state=false
        node.state = false
        self:_checkParentState(node)
    end

    -- 设置真实的state
    node.state = newState
    self:_dispatchRedPonitChange(node)

    if node.children then
        for k,child in pairs(node.children) do
            self:clearStateByKey(k, true)
        end
    end
end

function RedPonit:checkStateByKey(key, isCheckAllChildren)
    local node = self._redPointRoot[key]
    if not node then
        return
    end
    self:_checkRedPoint(node, isCheckAllChildren)

    -- print("====> RedPoint checkStateByKey", key, isCheckAllChildren)

    -- self:_debug()
end

function RedPonit:_checkRedPoint(node, isCheckAllChildren)
    if isCheckAllChildren then
        self:_initNode(node, true)
        self:_checkParentState(node)
    else
        -- dump(node, "====> RedPoint _checkRedPoint")

        local oldState = node.state
        local newState = oldState
        -- 当前节点
        if node.checkFunc then
            newState = node.checkFunc(node)
        end
        if not newState and node.children then
            for k, v in pairs(node.children) do
                if v.state then
                    newState = true
                    break
                end
            end
        end
        node.state = newState

        -- print("====> RedPoint state newState", oldState, newState)

        if node.state == oldState then
            return
        else
            self:_dispatchRedPonitChange(node)
            self:_checkParentState(node)
        end
    end
end

-- 回溯 父节点 状态
function RedPonit:_checkParentState(node)
    local parentNode = node.parent
    if parentNode then
        local oldState = parentNode.state
        local newState = false
        for k, v in pairs(parentNode.children) do
            if v.state then
                newState = true
                break
            end
        end
        -- 父节点 状态 没发生变化 停止 回溯
        if oldState == newState then
            return
        else
            -- 递归继续
            parentNode.state = newState
            self:_dispatchRedPonitChange(parentNode)
            self:_checkParentState(parentNode)
        end
    end
end

-- 提升效率 统一在下一帧 发送事件
function RedPonit:_dispatchRedPonitChange(node)
    self._changeKeys[node.key] = node.state
    if self._cronsIdx then
        return
    end
    self._cronsIdx = scheduler.newCron(function()
        -- dump(self._changeKeys, "====> RedPoint updateRedPoint")
        self._cronsIdx = nil
        self:dispatchChange(self._changeKeys)
        EM:notify(ViewEvent.Common_RedPonitChange, self._changeKeys)
        self._changeKeys = {}
    end, 0, false)
end

function RedPonit:_debug()
    for k, v in pairs(self._redPointRoot) do
        print("====> RedPoint === ", v.key, v.state)
    end
end


return RedPonit